package app

import (
	"net/http"
	"log"
	"fmt"
	"html/template"
	"time"
	"strings"
	"github.com/tidwall/gjson"
	"encoding/xml"
)

type LogResp struct {
	XMLName   xml.Name   `xml:"log"`
	Logentrys []Logentry `xml:"logentry"`
}

// Logentry svn logentry
type Logentry struct {
	Revision string    `xml:"revision,attr"`
	Author   string    `xml:"author"`
	DateTime string `xml:"date"`
	Msg      string    `xml:"msg"`
	Paths    []Path    `xml:"paths>path"`
}

// Path svn path
type Path struct {
	Action   string `xml:"action,attr"`
	PropMods string `xml:"prop-mods,attr"`
	TextMods string `xml:"text-mods,attr"`
	Kind     string `xml:"kind,attr"`
	Value    string `xml:",chardata"`
}

//代码发布项目管理
func (G *Global) DeployProjectManage(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		if HostList, Err := G.SelectAll("SELECT * FROM hosts"); Err == nil {
			if Project, Err := G.SelectAll("SELECT * FROM delpoy_project"); Err == nil {
				out := map[string]interface{}{"Global": G, "Project": Project, "HostList": HostList}
				t, template_err := template.ParseFiles("templates/deploy/project.html", "templates/common/head.html", "templates/common/foot.html")
				if template_err != nil {
					log.Println(template_err.Error())
					fmt.Fprintf(w, template_err.Error())
				} else {
					t.Execute(w, out)
				}
			} else {
				fmt.Println(Err.Error())
			}
		} else {
			fmt.Println(Err.Error())
		}
	} else if r.Method == "POST" { //添加项目
		operation_type := r.PostFormValue("operation_type")
		if operation_type == "add" { //添加操作
			ProjectNmae := r.PostFormValue("project_name") //项目名称
			ProjectType := r.PostFormValue("project_type") //项目类型
			ServerHostsList := strings.Replace(strings.TrimSpace(r.PostFormValue("server_host")), " ", "##", -1)
			// 判断项目名称是否重复
			if UrlInfo, Err := G.SelectOne("SELECT project_name FROM delpoy_project  where project_name = ?", ProjectNmae); Err == nil {
				if UrlInfo["project_name"] == ProjectNmae {
					fmt.Fprint(w, Get_Json("项目名称重复!"))
					return
				}
			} else {
				log.Println(Err.Error())
				fmt.Fprint(w, Get_Json("添加失败!"))
				return
			}
			// 插入数据库
			if _, Err := G.Insert("INSERT INTO delpoy_project (project_name, type,server_name,add_time) VALUES (?, ?,?, ?)",
				ProjectNmae, ProjectType, ServerHostsList, time.Now().Format("2006-01-02 15:04:05")); Err == nil {
				fmt.Fprint(w, Get_Json("Success"))
			} else {
				log.Println(Err.Error())
				fmt.Fprint(w, Get_Json("添加失败!"))
			}
		} else if operation_type == "del" { //删除操作
			if _, Err := G.Delete("DELETE FROM delpoy_project where id=?", r.PostFormValue("id")); Err == nil {
				fmt.Fprint(w, Get_Json("Success"))
			} else {
				log.Println(Err.Error())
				fmt.Fprint(w, Get_Json("删除失败!"))
			}
		}
	}
}

//代码发布函数
func (G *Global) Deploy(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		r.ParseForm()
		Projetc := r.Form["project"][0]
		if ProjectInfo, Err := G.SelectOne("SELECT id,edition from delpoy_project WHERE project_name=?", Projetc); Err == nil {
			if DelpoyLog, Err := G.SelectAll("SELECT * FROM deploy_logs WHERE project_id= ? ORDER BY id DESC LIMIT 5", ProjectInfo["id"]); Err == nil {
				if SvnCommitLogs, Err := G.SvnCommitLogs(G.Svn.Config["svn_addr"] + Projetc + "/" + G.Svn.Config["branch"] + "/"); Err == nil {
					out := map[string]interface{}{"Global": G, "SvnCommitLogs": SvnCommitLogs, "DelpoyLog": DelpoyLog, "Projetc": Projetc, "Edition": ProjectInfo["edition"], "ProjectId": ProjectInfo["id"]}
					if t, Err := template.ParseFiles("templates/deploy/deploy.html", "templates/common/head.html", "templates/common/foot.html"); Err != nil {
						log.Println(Err.Error())
						fmt.Fprintf(w, Err.Error())
					} else {
						t.Execute(w, out)
					}
				} else {
					log.Println(Err.Error())
				}
			} else {
				log.Println(Err.Error())
			}
		} else {
			log.Println(Err.Error())
		}
	} else if r.Method == "POST" {
		project_id := r.PostFormValue("project_id")
		project_edition := r.PostFormValue("project_edition")
		publisher := r.PostFormValue("publisher")
		restart := r.PostFormValue("restart")
		if ProjectInfo, Err := G.SelectOne("SELECT project_name,server_name,type from delpoy_project WHERE id=?", project_id); Err == nil {
			for _, hostname := range strings.Split(ProjectInfo["server_name"], "##") { //循环主机
				//判断/data/bin/updata.py 文件是否存在
				Value := fmt.Sprintf(strings.Replace(hostname, ".", `\.`, -1))
				post_cmd := fmt.Sprintf(`{"fun": "%s", "client": "%s", "tgt": "%s" ,"arg": "/data/bin/updata.py"}`, "file.file_exists", "local", hostname)
				if PostData, Err := G.CMD_SALT(post_cmd); Err == nil {
					if gjson.Get(PostData, fmt.Sprintf(`return.#.%s`, Value)).Array()[0].String() == "false" {
						G.Insert("insert into deploy_logs(project_id,publisher,deploy_time,edition,status) values (?,?,?,?,?)", project_id, publisher, time.Now().Format("2006-01-02 15:04:05"), project_edition, "/data/bin/updata.py 脚本不存在")
					} else {
						post_cmd := fmt.Sprintf(`{"fun": "%s", "client": "%s", "tgt": "%s" ,"arg": "/usr/bin/python /data/bin/updata.py --type=%s --etidion=%s --restart=%s --project=%s"}`, "cmd.run", "local", hostname, ProjectInfo["type"], project_edition, restart, ProjectInfo["project_name"])
						if PostData, Err := G.CMD_SALT(post_cmd); Err == nil { //调用salt api 执行更新操作
							//插入日志
							G.Insert("insert into deploy_logs(project_id,publisher,deploy_time,edition,status) values (?,?,?,?,?)", project_id, publisher, time.Now().Format("2006-01-02 15:04:05"), project_edition, gjson.Get(PostData, "return").Array()[0].String())
						} else {
							log.Println(Err.Error())
							fmt.Fprint(w, Get_Json("系统错误!"))
						}
					}
				} else {
					log.Println(Err.Error())
					fmt.Fprint(w, Get_Json("系统错误!"))
				}
			}
			G.Update("UPDATE delpoy_project set edition = ? WHERE id=?", project_edition, project_id)
			fmt.Fprint(w, Get_Json("Success"))
		} else {
			log.Println(Err.Error())
			fmt.Fprint(w, Get_Json("系统错误!"))
		}
	}
}

func (G *Global) SvnCommitLogs(svn_url string) (Data []map[string]template.HTML, Err error) {
	ret := make([]map[string]template.HTML, 0)
	post_cmd := fmt.Sprintf(`{"fun": "%s", "client": "%s", "tgt": "%s" ,"arg": "/usr/bin/svn log  --no-auth-cache --username %s --password %s  -l %s --xml -v %s"}`,
		"cmd.run", "local", G.Svn.Config["svn_shell_host"], G.Svn.Config["svn_user"], G.Svn.Config["svn_passwd"], G.Svn.Config["log_entries"], svn_url)
	if PostData, Err := G.CMD_SALT(post_cmd); Err == nil {
		v := LogResp{}
		if Err := xml.Unmarshal([]byte(gjson.Get(PostData, fmt.Sprintf(`return.#.%s`, strings.Replace(G.Svn.Config["svn_shell_host"], ".", `\.`, -1))).Array()[0].String()), &v); Err == nil {
			for _, b := range v.Logentrys {
				m1 := make(map[string]template.HTML)
				m1["Revision"] = template.HTML(b.Revision)
				m1["Author"] = template.HTML(b.Author)
				m1["DateTime"] = template.HTML(b.DateTime)
				m1["Msg"] = template.HTML(b.Msg)
				i := ""
				for _, l := range b.Paths {
					i += l.Value + "<br>"
				}
				m1["file"] = template.HTML(i)
				ret = append(ret, m1)
			}
			return ret, nil
		} else {
			return ret, Err
		}
	} else {
		return ret, Err
	}
}
